package com.kakaxi.mybilibili.net;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import com.kakaxi.mybilibili.utils.LogUtil;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.ProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.RedirectHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.impl.cookie.BasicClientCookie2;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.net.Socket;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
 * 支持访问https的httpClient的帮助类
 * Created by kakaxi on 16/12/1.
 */

public class HttpClientHelper {

    public static final int GET = 1;

    public static final int POST = 2;

    /** 统一浏览器 **/
    private static HttpClient mHttpClient;

    private HttpClientHelper() {
    }

    /**
     * 单例
     *
     * @return 浏览器
     */
    synchronized public static HttpClient getInstance() {
        if (mHttpClient == null) {
            try {
                mHttpClient = createSSLHttpClient();
                // 取消自动定向
                ((DefaultHttpClient) mHttpClient).setRedirectHandler(new RedirectHandler() {
                    @Override
                    public boolean isRedirectRequested(HttpResponse httpResponse, HttpContext
                            httpContext) {
                        return false;
                    }

                    @Override
                    public URI getLocationURI(HttpResponse httpResponse, HttpContext httpContext)
                            throws ProtocolException {
                        return null;
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        return mHttpClient;
    }

    /**
     * 发送请求
     *
     * @param httpClient 浏览器
     * @param method     发送类型
     * @param url        网址
     * @param paramList  内容参数
     * @param headers    请求头
     * @return 响应
     */
    public static HttpResponse request(HttpClient httpClient, int method, String url,
                                       List<BasicNameValuePair> paramList, Header[] headers) {

        if (url == null || url.trim().isEmpty()) {
            return null;
        }

        HttpResponse httpResponse = null;
        try {
            if (method == GET) {
                HttpGet httpGet = new HttpGet(url);
                if (headers != null) {
                    httpGet.setHeaders(headers);
                }
                httpResponse = httpClient.execute(httpGet);
            } else if (method == POST) {
                HttpPost httpPost = new HttpPost(url);
                if (paramList != null) {
                    HttpEntity entity = new UrlEncodedFormEntity(paramList);
                    httpPost.setEntity(entity);
                }
                if (headers != null) {
                    httpPost.setHeaders(headers);
                }
                httpResponse = httpClient.execute(httpPost);
            }

        } catch (IOException e) {
            e.printStackTrace();
            LogUtil.d("内部请求出错!");
        }
        return httpResponse;
    }

    /**
     * 发送请求
     *
     * @param httpClient 浏览器
     * @param url        链接
     * @param paramList  内容参数
     * @param headers    请求头数组
     * @return 响应
     */
    public static HttpResponse request(HttpClient httpClient, String url,
                                       List<BasicNameValuePair> paramList, Header[] headers) {
        return request(httpClient, paramList == null ? GET : POST, url, paramList, headers);
    }

    /**
     * 发送请求
     *
     * @param httpClient 浏览器
     * @param url        链接
     * @param paramList  内容参数
     * @return 响应
     */
    public static HttpResponse request(HttpClient httpClient, String url,
                                       List<BasicNameValuePair> paramList) {
        return request(httpClient, paramList == null ? GET : POST, url, paramList, null);
    }

    /**
     * 发送请求
     *
     * @param httpClient 浏览器
     * @param url        链接
     * @param headers    请求头数组
     * @return 响应
     */
    public static HttpResponse request(HttpClient httpClient, String url, Header[] headers) {
        return request(httpClient, GET, url, null, headers);
    }

    /**
     * 发送get请求
     *
     * @param httpClient 浏览器
     * @param url        链接
     * @return 响应
     */
    public static HttpResponse requset(HttpClient httpClient, String url) {
        return request(httpClient, GET, url, null, null);
    }

    /**
     * 判断是否响应成功
     *
     * @param httpResponse 响应
     * @return 是否成功
     */
    public static boolean isResponseSuccess(HttpResponse httpResponse) {
        if (httpResponse != null && httpResponse.getStatusLine().getStatusCode() == HttpStatus
                .SC_OK) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * @param httpResponse
     * @return
     */
    public static String getContentString(HttpResponse httpResponse) {
        HttpEntity httpEntity = httpResponse.getEntity();
        if (httpEntity != null) {
            try {
                return EntityUtils.toString(httpEntity);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * @param httpClient
     * @param method
     * @param url
     * @param paramList
     * @return
     */
    public static String quickRequest(HttpClient httpClient, int method, String url,
                                      List<BasicNameValuePair> paramList, Header[] headers) {
        HttpResponse httpResponse = request(httpClient, method, url, paramList, headers);
        if (httpResponse != null) {
            if (isResponseSuccess(httpResponse)) {
                return getContentString(httpResponse);
            }
        }
        return null;
    }

    /**
     * @param httpClient
     * @param url
     * @param paramList
     * @return
     */
    public static String quickRequest(HttpClient httpClient, String url,
                                      List<BasicNameValuePair> paramList, Header[] headers) {
        return quickRequest(httpClient, paramList == null ? GET : POST, url, paramList, headers);
    }

    /**
     * @param httpClient
     * @param url
     * @param paramList
     * @return
     */
    public static String quickRequest(HttpClient httpClient, String url,
                                      List<BasicNameValuePair> paramList) {
        return quickRequest(httpClient, paramList == null ? GET : POST, url, paramList, null);
    }

    /**
     * @param httpClient
     * @param url
     * @return
     */
    public static String quickRequest(HttpClient httpClient, String url, Header[] headers) {
        return quickRequest(httpClient, GET, url, null, headers);
    }

    /**
     * @param httpClient
     * @param url
     * @return
     */
    public static String quickRequest(HttpClient httpClient, String url) {
        return quickRequest(httpClient, GET, url, null, null);
    }

    /**
     * @param httpClient
     * @param url
     * @return
     */
    public static Bitmap requestToImage(HttpClient httpClient, String url) {
        HttpResponse httpResponse = requset(httpClient, url);
        if (httpResponse != null) {
            if (isResponseSuccess(httpResponse)) {
                try {
                    return BitmapFactory.decodeStream(httpResponse.getEntity().getContent());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * 添加cookie
     *
     * @param httpClient 浏览器
     * @param cookie     信息
     */
    public static void addCookie(HttpClient httpClient, BasicClientCookie2 cookie) {
        if (httpClient != null) {
            if (httpClient instanceof DefaultHttpClient) {
                DefaultHttpClient defaultHttpClient = (DefaultHttpClient) httpClient;
                defaultHttpClient.getCookieStore().addCookie(cookie);
            } else {

            }
        }
    }

    /**
     * 添加cookie数组
     *
     * @param httpClient 浏览器
     * @param cookieList 信息数组
     */
    public static void addCookie(HttpClient httpClient, List<BasicClientCookie2> cookieList) {
        for (BasicClientCookie2 cookie2 : cookieList) {
            addCookie(httpClient, cookie2);
        }
    }


    /**
     * 跳过https验证
     *
     * @throws Exception 出错
     */
    public static HttpClient createSSLHttpClient() throws Exception {
        KeyStore trustStore = KeyStore.getInstance(KeyStore
                .getDefaultType());
        trustStore.load(null, null);
        SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore);
        sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);  //允许所有主机的验证

        SSLContext ctx = SSLContext.getInstance("TLS");
        X509TrustManager tm = new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain,
                                           String authType) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain,
                                           String authType) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };
        ctx.init(null, new TrustManager[]{tm}, null);

        SchemeRegistry schReg = new SchemeRegistry();
        schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        schReg.register(new Scheme("https", sf, 443));

        HttpParams params = new BasicHttpParams();

        HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
        HttpProtocolParams.setContentCharset(params,
                HTTP.DEFAULT_CONTENT_CHARSET);
        HttpProtocolParams.setUseExpectContinue(params, true);

        ClientConnectionManager conManager = new ThreadSafeClientConnManager(
                params, schReg);

        return new DefaultHttpClient(conManager, params);
    }


    /**
     * ssl
     */
    static class SSLSocketFactoryEx extends SSLSocketFactory {

        SSLContext sslContext = SSLContext.getInstance("TLS");

        public SSLSocketFactoryEx(KeyStore truststore)
                throws NoSuchAlgorithmException, KeyManagementException,
                KeyStoreException, UnrecoverableKeyException {
            super(truststore);

            TrustManager tm = new X509TrustManager() {

                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                @Override
                public void checkClientTrusted(
                        java.security.cert.X509Certificate[] chain, String authType)
                        throws java.security.cert.CertificateException {

                }

                @Override
                public void checkServerTrusted(
                        java.security.cert.X509Certificate[] chain, String authType)
                        throws java.security.cert.CertificateException {

                }
            };

            sslContext.init(null, new TrustManager[]{tm}, null);
        }

        @Override
        public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
                throws IOException {
            return sslContext.getSocketFactory().createSocket(socket, host, port,
                    autoClose);
        }

        @Override
        public Socket createSocket() throws IOException {
            return sslContext.getSocketFactory().createSocket();
        }
    }

}
